#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#ifdef WIN32
#include "windows.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#include "pthread.h"

#include "BList.h"
#include "BVector.h"
#include "geometrics.h"
#include "quaternion.h"
#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"

#include "AWEntity.h"
#include "AWMessage.h"
#include "AWBrain.h"
#include "AWTracerBrain.h"
#include "AWThreadedBrain.h"
#include "AWNOOSBrain.h"
#include "AWNOOSLearnerBrain.h"

#include "loader.h"

#include "psm.h"


FeatureTerm *AW_NOOSLearnerBrain::solve_problem_simple_committee(FeatureTerm *problem,Sort *sort,Symbol *my_name)
{
	int i;
	char *str;
	AW_Message *m;
	Symbol *agent_name;
	List<Symbol> agent_names;
	FeatureTerm *solution,*f,*op;
	List<FeatureTerm> individual_solutions;

	/* Retrieve the set of other agents: */ 
	pthread_mutex_lock(&m_sensor_data_mutex);
	m_sensor_data.Rewind();
	while(m_sensor_data.Iterate(f)) {						
		if (f->getSort()->is_a(m_ontology->get_sort("sensed-agent")) &&
			!f->getSort()->is_a(m_ontology->get_sort("sensed-self"))) {
			Symbol *name=f->featureValueQuick("name")->getSymbol();
			if (name->get()[0]=='L' &&
				name->get()[1]=='e' &&
				name->get()[2]=='a' &&
				name->get()[3]=='r' &&
				name->get()[4]=='n' &&
				name->get()[5]=='e' &&
				name->get()[6]=='r') {
				agent_names.Add(new Symbol(name));
			} /* if */ 
		} /* if */ 
	} /* while */ 
	pthread_mutex_unlock(&m_sensor_data_mutex);

	/* Do not use all the agents: */ 
/*
	{
//		delete agent_names.ExtractIni();
		delete agent_names.ExtractIni();
		delete agent_names.ExtractIni();
		delete agent_names.ExtractIni();
	}
*/

	/* Send the problem to the other agents: */ 
	f=0;
	str=0;
	agent_names.Rewind();
	while(agent_names.Iterate(agent_name)) {
		/* Send the problem: */ 
		if (f==0) {
			f=new FeatureTerm((char *)0,m_ontology->get_sort("request-individual-predict-message"),1,
							  "problem",new FeatureTerm(problem));

			str=f->toStringNOOS(m_memory);
		} /* if */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(agent_name),m_ontology),
						   "content",new FeatureTerm(0,new Symbol(str),m_ontology));
		enqueue_operator(op);
	} /* while */ 
	if (f!=0) {
		delete []str;
		delete f;
	} /* if */ 

	/* Solve the problem individually: */ 
	individual_solutions.Add(build_jers(problem,sort,my_name));

	/* Receive the solution from the others: */ 
	for(i=0;i<agent_names.Length();i++) {
		/* Wait for the confirmation of the agent: */ 
		wait_message();
		m=get_message();
		solution=FeatureTerm::fromStringNOOS(m->content->get(),m_memory,m_ontology);
		individual_solutions.Add(solution);
		delete m;
	} /* for */ 

	/* Aggregate the solutions: */ 
	return majority_voting(&individual_solutions);
} /* AW_NOOSLearnerBrain::solve_problem_committee */ 


FeatureTerm *AW_NOOSLearnerBrain::majority_voting(List<FeatureTerm> *predictions)
{
	int pos;
	float v;
	FeatureTerm *solution;
	List<FeatureTerm> solutions,*l;
	List<float> votes;
	FeatureTerm *solution_record,*prediction,*prediction2;

	predictions->Rewind();
	while(predictions->Iterate(prediction)) {

		/* Compute votes: */ 
		if (prediction->isSet()) {
			l=prediction->set_values_quick();
			l->Rewind();
			while(l->Iterate(prediction2)) {
				solution=prediction2->featureValueQuick("solution");
				pos=solutions.Position(solution);
				if (pos==-1) {
					solutions.Add(new FeatureTerm(solution));
					votes.Add(new float(1.0f));
				} else {
					*votes[pos]=*votes[pos]+1.0f;
				} /* if */ 
			} /* while */ 
		} else {
			solution=prediction->featureValueQuick("solution");
			pos=solutions.Position(solution);
			if (pos==-1) {
				solutions.Add(new FeatureTerm(solution));
				votes.Add(new float(1.0f));
			} else {
				*votes[pos]=*votes[pos]+1.0f;
			} /* if */ 
		} /* if */ 
		
	} /* while */ 

	if (solutions.Length()==0) return 0;

	/* Get the most voted solution: */ 
	solution=solutions[0];
	v=*votes[0];

	for(pos=0;pos<solutions.Length();pos++) {
		if (*votes[pos]>v) {
			solution=solutions[pos];
			v=*votes[pos];
		} /* if */ 
	} /* for */ 

	solution_record=new FeatureTerm((char *)0,m_ontology->get_sort("problem-prediction"),1,
									"solution",new FeatureTerm(solution));

	return solution_record;
} /* AW_NOOSLearnerBrain::majority_voting */ 
